#coding=utf-8
from __future__ import with_statement
from uliweb import expose
from datetime import date, timedelta
from uliweb.orm import get_model
import logging

log = logging.getLogger('uliweb.app')
def __begin__():
    from uliweb import function
    return function('require_login')()
    
@expose('/weekreport')
class Weekreport(object):
    def __init__(self):
        self.model = get_model('weekreport')
        
    def _create_query(self, url):
        """
        创建查询View
        """
        from uliweb.orm import get_model
        from uliweb.utils.generic import QueryView
        from plugs.ui.jquery.uimultiselect.widgets import UIMultiSelectField
        from uliweb.form import UnicodeField, SelectField
        from uliweb.utils.generic import ReferenceSelectField
        from query.forms import QueryForm
        from plugs.ui.jquery.uimultiselect.widgets import UIMultiSelectField
        from datetime import timedelta
        
#        def get_record(model):
#            def _f(id):
#                from uliweb.orm import get_model
#                
#                if id:
#                    obj = get_model(model).get(int(id))
#                    if obj:
#                        return [(obj.id, unicode(obj))]
#                return [('', '')]
#            return _f
#        
#        Requirement = get_model('requirement')
#        requirement = JQComboBoxField(label='准开发需求', url='/requirements/query', get_record=get_record('requirement'))
        requirement_title = UnicodeField(label='准开发需求')
        tx = ReferenceSelectField('tx', label='条线')
        kfzx = ReferenceSelectField('kfzx', label='开发中心')
        care_level = UIMultiSelectField('关注级别', choices=settings.get_var('PARA/CARE_LEVEL'))
        mode = UIMultiSelectField('实施方式', choices=settings.get_var('PARA/REQ_MODE'))
        closed = SelectField('显示非在建', choices=settings.get_var('PARA/YES_NO'), default='0')
        fields = [('requirement_title', requirement_title), 'begin_date', 
            'end_date', ('tx', tx), ('care_level', care_level), ('mode', mode),
            ('closed', closed), ('kfzx', kfzx)] 
        layout = [('requirement_title', 'care_level', 'closed'), 
            ('begin_date', 'end_date', 'tx', 'kfzx'), ('mode',)]
        begin, end = self._get_cur_week_date()
        begin, end = begin - timedelta(days=7), end - timedelta(days=7)
        query = QueryView(self.model, ok_url=url, fields=fields, layout=layout,
            form_cls=QueryForm)
        return query

    def list(self):
        """
        周报列表
        """
        
        from uliweb.utils.generic import ListView, get_sort_field
        from uliweb.orm import get_model
        
        Requirement = get_model('requirement')
        
        query = self._create_query(url_for(self.__class__.list))
        c = query.run()
        
        condition = None
        if c.get('begin_date'):
            condition = (self.model.c.begin_date >= c['begin_date']) & condition
        if c.get('end_date'):
            condition = (self.model.c.end_date <= c['end_date']) & condition
        _con = None
        if c.get('requirement_title'):
            _con = Requirement.c.title.like('%'+c['requirement_title']+'%') | Requirement.c.req_id.like('%'+c['requirement_title']+'%')
            _r = Requirement.filter(_con).values('id')
            req_ids = [x[0] for x in _r]
            if req_ids:
                condition = (self.model.c.requirement.in_(req_ids)) & condition
            else:
                condition = self.model.c.id != self.model.c.id
        
        if c.get('tx'):
            condition = (self.model.c.tx == int(c['tx'])) & condition
        if c.get('care_level'):
            condition = self.model.c.care_level.in_(c['care_level']) & condition
        if c.get('mode'):
            condition = self.model.c.mode.in_(c['mode']) & condition
        if c.get('kfzx'):
            condition = (self.model.c.kfzx == c['kfzx']) & condition
            
        if c.get('closed') == '1':
            condition = (self.model.c.requirement == Requirement.c.id) & (Requirement.c.stage != 'FN') & condition
            
        pageno = int(request.values.get('page', 1)) - 1
        rows_per_page=int(request.values.get('rows', settings.get_var('PARA/ROWS_PER_PAGE', 10)))

        order_by = get_sort_field(self.model) or []
        order_by.append(self.model.c.begin_date.desc())
        
        def _id(value, obj):
            return '<a href="/weekreport/view?id=%d">%d</a>' % (value, value)
        
        def pre_execute(value, obj):
            return '%.1f%%' % (value * 100)
        
        def plan_resource_center(value, obj):
            return '%.1f' % value
        
        def input_center_per(value, obj):
            return '%.1f%%' % (value * 100)
        
        def plan_resource_company(value, obj):
            return '%.1f' % value
        
        def input_company_per(value, obj):
            return '%.1f%%' % (value * 100)
        
        def title(value, obj):
            return '<a href="/weekreport/view?id=%d">%s</a>' % (obj.id, obj.title)
        
        fields_convert_map = {'id':_id, 'pre_execute':pre_execute,
            'plan_resource_center':plan_resource_center, 'input_center_per':input_center_per,
            'plan_resource_company':plan_resource_company, 'input_company_per':input_company_per,
            'title':title}
        view = ListView(self.model, condition=condition, fields_convert_map=fields_convert_map, 
            order_by=order_by, rows_per_page=rows_per_page, pageno=pageno)
        if 'data' in request.values:
            return json(view.json())
        elif 'download' in request.values:
            fields_convert_map = {}
            return view.download('weekreport.xls', action='download', timeout=0,
                fields_convert_map=fields_convert_map)
        else:
            result = view.run(head=True, body=False)
            result.update({'query_form':query.form, 'table':view})
            return result
        
    def view(self):
        Requirement = get_model('requirement')
        begin, end = self._get_cur_week_date()
        if request.GET.get('id'):
            obj = self.model.get(int(request.GET.get('id')))
        requirement = request.GET.get('requirement')
        if requirement:
            obj = self.model.get((self.model.c.requirement==int(requirement)) & (self.model.c.begin_date==begin) & (self.model.c.end_date==end))
            if not obj:
                req = Requirement.get(int(requirement))
                if not req:
                    error("对应的准开发需求不存在")
                obj = self.model(requirement=int(requirement), begin_date=begin, 
                    end_date=end, title=req.title, req_id=req.req_id, care_level=req.care_level,
                    mode=req.mode, tx=req.tx, tx_manager=req.tx_manager,
                    submitter=req.submitter, contactor=req.contactor,
                    exe_manager=req.exe_manager, main_sys=req.main_sys)
                obj.save()
        
        return self._view(obj=obj)
    
    def _view(self, obj=None, print_flag=False):
        """
        周报显示
        """
        
        from uliweb.utils.generic import DetailView
        from uliweb.orm import get_model
        
        WeekReport = get_model('weekreport')
        Requirement = get_model('requirement')
        begin, end = self._get_cur_week_date()
        
        def can_write_desc():
            """
            判断用户是否可以编辑当前系统，并且当前日期需要在周报日期之内
            """
            if request.user.users_systems.has(obj._main_sys_) and obj.begin_date==begin and obj.end_date==end:
                return True
            else:
                return False
            
        def assignments(value, obj):
            s = []
            txt = ''
            for row in obj.assignments.all():
                s.append(u'<li><a href="/assignments/%d"  title="项目编号：%s">%s</a></li>' % (row.id, row.ass_id, row.name))
            if len(s) > 2 and not print_flag:
                txt = '<div class="noul"><div>' + '\n'.join(s[:2]) + '</div>'
                txt += u'<div class="more_link"><a href="javascript:void(0)">更多&gt;&gt;</a></div>' + '<div class="more">' + '\n'.join(s[2:]) + '</div>'
                txt += '</div>'
            else:
                txt = '<div class="noul">' + '\n'.join(s) + '</div>'
            return txt
        
        def cokfzx(obj):
            kfzxs = []
            for row in obj.systems.all():
                if row.kfzx.name not in kfzxs:
                    kfzxs.append(row.kfzx.name)
            return ' '.join(kfzxs)
        
        template_data = {
            'can_write_desc':can_write_desc, 
            'cokfzx':cokfzx,
            'questions_list':self._questions_list(obj.id),
            'risks_list':self._risks_list(obj.id),
            'cur_plans':self._cur_plans(obj.id),
            'next_plans':self._next_plans(obj.id),
            'layout':'charts_layout.html',
            'print_flag':print_flag,
        }
            
        fields_convert_map = {'assignments':assignments}
        view = DetailView(self.model, obj=obj,
            fields_convert_map=fields_convert_map,
            template_data=template_data)
        return view.run()
        
    def _questions_list(self, id):
        """
        问题列表
        """
        
        from uliweb.utils.generic import ListView
        from uliweb.orm import get_model
        
        QuestionHis = get_model('questionhis')
        
        condition = QuestionHis.c.weekreport == int(id)
            
        def _id(value, obj):
            return '<a href="/weekreport/question_view/%d">%d</a>' % (value, value)
        
        def title(value, obj):
            return '<a href="/weekreport/question_view/%d">%s</a>' % (obj.id, value)
        
        fields_convert_map = {'id':_id, 'title':title}
        view = ListView(QuestionHis, condition=condition, pagination=False,
            table_width=False, fields_convert_map=fields_convert_map, 
            id='questions_table', table_class_attr='q-table fix-header')
        if self.model.filter(condition).count() == 0:
            return {'table':'', 'info':{'total':0}}
        return view.run(head=True, body=True)
    
    def question_view(self, id):
        """
        问题显示
        """
        
        from uliweb.utils.generic import DetailView
        from uliweb.orm import get_model
        
        Question = get_model('questionhis')
        
        obj = Question.get(int(id))
        view = DetailView(Question, obj=obj)
        return view.run()

    def _risks_list(self, id):
        """
        风险列表
        """
        
        from uliweb.utils.generic import ListView
        from uliweb.orm import get_model
        
        RiskHis = get_model('riskhis')
        
        condition = RiskHis.c.weekreport == int(id)
            
        def _id(value, obj):
            return '<a href="/weekreport/risk_view/%d">%d</a>' % (value, value)
        
        def title(value, obj):
            return '<a href="/weekreport/risk_view/%d">%s</a>' % (obj.id, value)
        
        def degree(value, obj):
            return '%.2f' % (obj.probability * obj.serious)
        
        fields_convert_map = {'id':_id, 'title':title, 'degree':degree}
        view = ListView(RiskHis, condition=condition, pagination=False,
            table_width=False, fields_convert_map=fields_convert_map, 
            id='risks_table', table_class_attr='q-table fix-header')
        if self.model.filter(condition).count() == 0:
            return {'table':'', 'info':{'total':0}}
        return view.run(head=True, body=True)
    
    def risk_view(self, id):
        """
        风险显示
        """
        
        from uliweb.utils.generic import DetailView
        from uliweb.orm import get_model
        
        Risk = get_model('riskhis')
        
        obj = Risk.get(int(id))
        view = DetailView(Risk, obj=obj)
        return view.run()
    
    def _get_next_week_date(self, today=None):
        today = today or date.today()
        begin = today + timedelta(days=(7-(today.weekday()+2)%7))
        end = begin + timedelta(days=6)
        return begin, end
    
    def _get_cur_week_date(self, today=None):
        today = today or date.today()
        begin = today - timedelta(days=(today.weekday()+2)%7)
        end = begin + timedelta(days=6)
        return begin, end
        
    def write(self, id):
        """
        添加项目进展描述
        """
        from uliweb.utils.generic import EditView
        from uliweb.utils.textconvert import text2html
        
        def success_data(obj):
            return text2html(obj.field_str(obj.description))
        
        obj = self.model.get(int(id))
        view = EditView(self.model, success_data=success_data, form_args={'action':request.path, 
            'html_attrs':{'id':'edit_desc_form'}}, obj=obj, meta='EditDescForm')
        return view.run(json_result=True)

    def _cur_plans(self, id):
        """
        本周计划
        """
        from uliweb.utils.generic import ListView, make_view_field
        from uliweb.orm import get_model
        from uliweb.core.html import Tag
        from uliweb.utils.common import date_in
    
        PlanExecuteHis = get_model('planexecutehis')
        PlanHis = get_model('planhis')
        Task = get_model('tasks_develop')
        WeekReport = get_model('weekreport')

        week = WeekReport.get(int(id))
        tasks = {}
        
        table = []
        total = 0
        
        def make_task(task):
            tr = Tag('tr', _class='task')
            with tr:
                with tr.td(colspan=4):
                    tr << '<a href="/tasks/develop/%d">任务：%s</a>' % (task.id, task.name.encode('utf-8'))
                with tr.td(colspan=3, align='right'):
                    tr << '<b>投产时间：</b>' + task.field_str(task.version_date, strict=True)
#                with tr.td:
#                    tr << '<b>状态：</b>' + make_view_field(Task.status, task)['display']
            return str(tr)
            
        def make_plan(row):
            tr = Tag('tr', _class='plan')
            with tr:
                with tr.td:
                    if row.type == '1':
                        tr << '<span class="plan">阶段</span>'
                    else:
                        tr << '<span class="milestone">里程碑</span>'
                with tr.td(colspan=6):
#                    tr << '<span class="tree_indent"></span>'
                    tr << row.title
                    if row.type == '1':
                        tr << '(%s - %s)' % (row.field_str(row.begin_date), row.field_str(row.end_date))
                    else:
                        tr << '(%s)' % row.field_str(row.end_date)
                    tr << '<b>执行系统：</b>'
                    tr << make_view_field(PlanHis.systems, row)['display']
            return str(tr)
        
        def make_execute(row):
            """
            row 为planexecute记录
            """
            from uliweb.orm import get_model
            
            not_fill = '<span class="not_fill">未填写</span>'
            
            Detail = get_model('planexecutedetails')
            PlanExecute = get_model('planexecute')
            
            d = Detail.get((Detail.c.begin_date==week.begin_date)&(Detail.c.end_date==week.end_date)&(Detail.c.planexecute==row.old_id))
            tr = Tag('tr', _class='execute')
#            #flag用来判断是否在本周内同步过本周情况，如果有则直接使用
#            flag = date_in(row.sync_date, [week.begin_date, week.end_date])
            with tr:
                with tr.td(align="center"):
                    tr << '<a href="/tasks/develop/%d" title="跳转到相应的任务">»</a>' % row._task_
                with tr.td:
#                    tr << '<span class="tree_indent"></span>' * 2
                    tr << '<a href="/systems/%d" title="%s">%s(%s)</a>' % (row._system_, row.system.name, row.system.abbr, row.system.name)
                    if row.task.sub_sys:
                        tr << "[<span title='%s'>%s<span>]" % (row.task.sub_sys_name.encode('utf-8'), row.task.sub_sys.encode('utf-8'))
                with tr.td:
                    if d:
                        tr << (make_view_field(Detail.desc, d)['display'] or not_fill)
                    else:
                        tr << not_fill
                with tr.td(align='center'):
                    if row.status == '2':
                        #如果延迟，则显示为特殊样式
                        tr << '<div class="delay">%s</div>' % make_view_field(PlanExecute.status, row)['display']
                    else:
                        tr << make_view_field(PlanExecute.status, row)['display']
                with tr.td(align='center'):
                    if row.type == '1':
                        tr << '%s - %s' % (row.field_str(row.finish_begin_date) or '未完成', row.field_str(row.finish_end_date) or '未完成')
                    else:
                        tr << '%s' % (row.field_str(row.finish_end_date) or '未完成')
                with tr.td(align='center'):
                    if row.finish_end_date:
                        tr << '100%'
                    else:
                        if d:
                            tr << '%.0f%%' % (d.finish*100)
                        else:
                            tr << '%.0f%%' % (row.finish*100)
                with tr.td:
                    if d:
                        tr << d.executer
                    else:
                        tr << row.executer
                    
            return str(tr)

        def make_table():
            def _cmp_task(x, y):
                if not x['version_date']:
                    return 1
                if not y['version_date']:
                    return -1
                return cmp(x['version_date'], y['version_date'])
            
            def _cmp_plan(x, y):
                return cmp(x['end_date'], y['end_date'])
            
            def _cmp_execute(x, y):
                return cmp(x['abbr'], y['abbr'])

            table.append('<table class="week-plan fix-header">')
            table.append('<tbody>')
            for _task in sorted(tasks.itervalues(), _cmp_task):
                table.append(_task['txt'])
                table.append('<tr class="title"><th>&nbsp;</th><th>系统名称</th><th>本周情况</th><th>状态</th><th>实际完成时间</th><th>进度</th><th>执行人</th></tr>')
                for _plan in sorted(_task['plans'].itervalues(), _cmp_plan):
                    table.append(_plan['txt'])
                    for _execute in sorted(_plan['executes'].itervalues(), _cmp_execute):
                        table.append(_execute['txt'])
            table.append('</tbody>')
            table.append('</table>')
            return '\n'.join(table)
        
        for row in PlanExecuteHis.filter(PlanExecuteHis.c.weekreport==int(id)):
            p = PlanHis.get((PlanHis.c.old_id==row._plan_) & (PlanHis.c.flag=='1') & (PlanHis.c.weekreport==int(id)))
            if not p:
                continue
            task_del_flag = 0
            for row_t in Task.filter(Task.c.id == row._task_):
                task_del_flag = 1
            if task_del_flag == 0:
                continue
            total += 1
            
            t = row.task
            if row.task.version_headerId:
                t = row.task.version_headerId
            plan = p
            if t.id not in tasks:
                tasks[t.id] = {'version_date':t.version_date,
                    'plans':{}, 'txt':make_task(t), 'id':t.id}
            if p.id not in tasks[t.id]['plans']:
                tasks[t.id]['plans'][p.id] = {'id':p.id, 
                    'executes':{}, 'txt':make_plan(p), 'end_date':p.end_date}
            p = tasks[t.id]['plans'][p.id]
            p['executes'][row.id] = {'id':row.id, 
                'txt':make_execute(row), 'system':row.system.name.encode('utf-8'),
                'system_id':row._system_, 'abbr':row.system.abbr.encode('utf-8'),
            }
            
        return {'table':make_table(), 'total':total}
    
    def _next_plans(self, id):
        """
        下周计划
        """
        from uliweb.utils.generic import ListView, make_view_field
        from uliweb.orm import get_model, NotFound
        from uliweb.core.html import Tag
        from uliweb.utils.common import date_in
    
        PlanHis = get_model('planhis')
        Task = get_model('tasks_develop')
        WeekReport = get_model('weekreport')

        week = WeekReport.get(int(id))
        tasks = {}
        
        table = []
        total = 0
        
        def make_task(task):
            tr = Tag('tr', _class='task')
            with tr:
                with tr.td(colspan=3):
                    tr << '<a href="/tasks/develop/%d">任务：%s</a>' % (task.id, task.name.encode('utf-8'))
                with tr.td(colspan=2, align='right'):
                    tr << '<b>投产时间：</b>' + task.field_str(task.version_date or '无')
            return str(tr)
            
        def make_plan(row):
            tr = Tag('tr', _class='execute')
            with tr:
                with tr.td:
                    if row.type == '1':
                        tr << '<span class="plan">阶段</span>'
                    else:
                        tr << '<span class="milestone">里程碑</span>'
                with tr.td:
#                    tr << '<span class="tree_indent"></span>'
                    tr << row.title
                with tr.td(align='center'):
                    if row.type == '1':
                        tr << '%s - %s' % (row.field_str(row.begin_date), row.field_str(row.end_date))
                    else:
                        tr << '%s' % row.field_str(row.end_date)
                with tr.td:
                    tr << make_view_field(PlanHis.systems, row)['display']
                with tr.td:
                    tr << row.responsible
            return str(tr)
        
        def make_table():
            def _cmp_task(x, y):
                if not x['version_date']:
                    return 1
                if not y['version_date']:
                    return -1
                return cmp(x['version_date'], y['version_date'])
            
            def _cmp_plan(x, y):
                return cmp(x['end_date'], y['end_date'])
            
            def _cmp_execute(x, y):
                return cmp(x['abbr'], y['abbr'])

            table.append('<table class="week-plan fix-header">')
            table.append('<tbody>')
            for _task in sorted(tasks.itervalues(), _cmp_task):
                table.append(_task['txt'])
                table.append('<tr class="title"><th>&nbsp;</th><th>计划名称</th><th>计划时间</th><th>执行系统</th><th>责任人</th></tr>')
                for _plan in sorted(_task['plans'].itervalues(), _cmp_plan):
                    table.append(_plan['txt'])
                    for _execute in sorted(_plan['executes'].itervalues(), _cmp_execute):
                        table.append(_execute['txt'])
            table.append('</tbody>')
            table.append('</table>')
            return '\n'.join(table)
        
        for plan in PlanHis.filter(PlanHis.c.weekreport==int(id)).filter(PlanHis.c.flag=='2'):
            total += 1
            
            try:
                t = plan.task
                if plan.task.version_headerId:
                    t = plan.task.version_headerId
                if t.id not in tasks:
                    tasks[t.id] = {'version_date':t.version_date,
                        'plans':{}, 'txt':make_task(t), 'id':t.id}
                if plan.id not in tasks[t.id]['plans']:
                    tasks[t.id]['plans'][plan.id] = {'id':plan.id, 
                        'executes':{}, 'txt':make_plan(plan), 'end_date':plan.end_date}
            except NotFound, e:
                log.info('Task %d is not exsited' % plan._task_)
            
        return {'table':make_table(), 'total':total}

    def search(self, week_id):
        from forms import WeekSearchForm
        from uliweb.orm import get_model
        from datetime import timedelta
        
        WeekReport = get_model('weekreport')
        
        week = WeekReport.get(int(week_id))
        form = WeekSearchForm()
        if form.validate(request.values):
            if form.data['week']:
                if form.data['week'] == 'prev':
                    begin, end = self._get_cur_week_date(form.data['date'] - timedelta(days=7))
                else:
                    begin, end = self._get_cur_week_date(form.data['date'] + timedelta(days=7))
            elif form.data['date']:
                date = form.data['date']
                begin, end = self._get_cur_week_date(date)
            else:
                return json({'success':False, 'message':'没有输入日期字段'})
            w = WeekReport.get((WeekReport.c.begin_date==begin) & (WeekReport.c.end_date==end) & (WeekReport.c.requirement==week._requirement_))
            if w:
                return json({'success':True, 'data':w.id})
            else:
                return json({'success':False, 'message':'没有满足条件的周报'})
            
        else:
            return json({'success':False, 'message':'处理出错'})
        
    @expose('print/<id>')
    def print_view(self, id):
        obj = self.model.get(int(id))
        result = self._view(obj, print_flag=True)
        result['layout'] = 'Weekreport/print_layout.html'
        result['print_flag'] = True
        return result